/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2010.

	This file is part of the Maxsi Library.

	Maxsi Library is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi Library is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
	or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
	License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Library. If not, see <http://www.gnu.org/licenses/>.

	Maxsi Library
	A powerful Cross-Platform C++ General Purpose Library that allows you to
	efficiently create high-performance and reliable applications.

	MaxsiWindowGTK.cpp
	Implements the MaxsiWindowSystem using the GTK+ platform.

******************************************************************************/

#include "MaxsiLibrary.h"

#ifdef Maxsi_Support_GTK

BeginMaxsiNamespace

MaxsiWindowSystemGTK::MaxsiWindowSystemGTK()
{
	
}

MaxsiWindowSystemGTK::~MaxsiWindowSystemGTK()
{
	if ( ControlSystem ) { DeleteControlSystem(ControlSystem); }
}

MaxsiControlSystem* MaxsiWindowSystemGTK::GetControlSystem()
{
	if ( ControlSystem == NULL ) { ControlSystem = CreateControlSystem(); }

	if ( ControlSystem ) { ControlSystem->SetWindowSystem(this); }

	return ControlSystem;
}

MaxsiControlSystem* MaxsiWindowSystemGTK::CreateControlSystem()
{
	return new MaxsiControlSystemGTK;
}

bool MaxsiWindowSystemGTK::DeleteControlSystem(MaxsiControlSystem* ControlSystem)
{
	delete (MaxsiControlSystemGTK*)ControlSystem;
	return true;
}

int MaxsiWindowSystemGTK::Initialize(int* argc, char*** argv)
{
	if ( gtk_init_check(argc, argv) == FALSE ) { return 0; }

	return 1;
}

int MaxsiWindowSystemGTK::MainLoop()
{
	gtk_main();
	return 0;
}

MaxsiHandle MaxsiWindowSystemGTK::CreateWindow(MaxsiHandle Parent, int Width, int Height, int Left, int Top, MESTR* Title)
{
	GtkWidget*	Window	= gtk_window_new(GTK_WINDOW_TOPLEVEL);

	if (!Window) { return NULL; }

	char*	WindowTitleSL	=	MESTR2CHAR(Title); // GTK+ only accept system locale input for the window title.

	// It is not a critical error if the memory allocation failed.

	gtk_window_set_title(GTK_WINDOW(Window), WindowTitleSL);

	if ( WindowTitleSL != NULL ) { delete[] WindowTitleSL; }

	gtk_window_set_default_size(GTK_WINDOW(Window), Width, Height);
	gtk_window_set_position(GTK_WINDOW(Window), GTK_WIN_POS_CENTER);

	//if (!Frame) { Frame = gtk_fixed_new(); }
	//if (!Frame) { return NULL; }

 	//gtk_container_add(GTK_CONTAINER(Window), Frame);

	g_signal_connect_swapped(G_OBJECT(Window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

	return (MaxsiHandle)Window;	
}

bool MaxsiWindowSystemGTK::ShowWindow(MaxsiHandle Window)
{
	gtk_widget_show(GTK_WIDGET((GtkWidget*)Window));

	return true;
}

bool MaxsiWindowSystemGTK::HideWindow(MaxsiHandle Window)
{
	gtk_widget_hide(GTK_WIDGET((GtkWidget*)Window));

	return true;
}

#if 0
bool MaxsiWindowGTK::CreateWindow(int WindowWidth, int WindowHeight)
{
	if (!GetWindowSystem()) { return false; }

	if (!Window) { Window = gtk_window_new(GTK_WINDOW_TOPLEVEL); }
	if (!Window) { return false; }

	MESTR*	WindowTitle		=	GetWindowTitle();
	char*	WindowTitleA	=	MESTRAP(WindowTitle); // GTK+ only accept ascii input for the window title.

	gtk_window_set_title(GTK_WINDOW(Window), WindowTitleA);

	MESTRUAP(WindowTitleA);
	delete[] WindowTitle;

	if ( WindowWidth == 0 ) { WindowWidth = GetDefaultWidth(); }
	if ( WindowHeight == 0 ) { WindowHeight = GetDefaultHeight(); }

	gtk_window_set_default_size(GTK_WINDOW(Window), WindowWidth, WindowHeight);
	gtk_window_set_position(GTK_WINDOW(Window), GTK_WIN_POS_CENTER);

	if (!Frame) { Frame = gtk_fixed_new(); }
	if (!Frame) { return false; }

 	gtk_container_add(GTK_CONTAINER(Window), Frame);

	Width	=	WindowWidth;
	Height	=	WindowHeight;

	if ( !CreateControls() ) { return false; }
	
	if ( !UpdateWindow() ) { return false; }

	gtk_widget_show_all(Window);

	g_signal_connect_swapped(G_OBJECT(Window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

	return true;
}
#endif

MaxsiHandle MaxsiWindowSystemGTK::CreatePictureBufferFromFile(MESTR* FileName)
{
	// Convert the file name to the system locale.
	char*	FileNameSL	=	MESTR2CHAR(FileName);

	if ( !FileNameSL ) { return NULL; }

	GError*		Error		=	NULL;
	GdkPixbuf*	Picture		=	gdk_pixbuf_new_from_file(FileNameSL, &Error);

	delete[] FileNameSL;

	return (MaxsiHandle)Picture;
}

bool MaxsiWindowSystemGTK::DeletePictureBuffer(MaxsiHandle PictureBuffer)
{
	// I don't know how to delete the results of gdk_pixbuf_new_from_file()!
	// We got a memory leak here!

	return false;
}

bool MaxsiWindowSystemGTK::SetWindowIcon(MaxsiHandle Window, MaxsiHandle Icon)
{
	gtk_window_set_icon(GTK_WINDOW((GtkWidget*)Window), (GdkPixbuf*)Icon);

	return true;
}

int MaxsiWindowSystemGTK::MoveWindowControl(MaxsiHandle Parent, MaxsiHandle Control, int Top, int Left, int Width, int Height, bool UnusedInLinux)
{
	gtk_widget_set_size_request(GTK_WIDGET((GtkWidget*)Control), Width, Height);
	gtk_fixed_put(GTK_FIXED(Parent), GTK_WIDGET((GtkWidget*)Control), Top, Left);

	return 1;
}


int MaxsiWindowSystemGTK::MsgBox(MaxsiHandle Parent, int Flags, MESTR* ErrorMessage, MESTR* ErrorTitle)
{
	// Create an error dialog.
	GtkWidget* Dialog = gtk_message_dialog_new((GtkWindow*)NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%S", ErrorTitle);

	if ( Dialog == NULL ) { return 0; }

	gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(Dialog), "%S", ErrorMessage);

	// Display the error dialog and wait for it to close.
	gtk_dialog_run(GTK_DIALOG(Dialog));

	// Delete the error dialog when it has been closed.
	gtk_widget_destroy(Dialog);

	return 1;
}

MaxsiError MaxsiWindowSystemGTK::GetWindowSize(MaxsiHandle Window, int* Left, int* Top, int* Width, int* Height)
{
	MAXSI_TODO("According to the official documentation, we are dealing with a race conditions here. Please fix this.");

	gtk_window_get_position(GTK_WINDOW((GtkWindow*)Window), (gint*)Left, (gint*)Top);
	gtk_window_get_size(GTK_WINDOW((GtkWindow*)Window), (gint*)Width, (gint*)Height);

	return MAXSI_ERROR_SUCCESS;
}

MaxsiError MaxsiWindowSystemGTK::UpdateWindow(MaxsiHandle Window)
{
	return MAXSI_ERROR_SUCCESS;
}

MaxsiHandle MaxsiWindowSystemGTK::GetDefaultBoldFont()
{
	return (MaxsiHandle)1;
}

	
MaxsiHandle MaxsiWindowSystemGTK::GetControlParent(MaxsiHandle Window, MaxsiHandle Frame)
{
	return Frame;
}



bool MaxsiControlSystemGTK::DeleteControl(MaxsiHandle Control)
{
	return false;
}

MaxsiHandle MaxsiControlSystemGTK::CreateFrame(MaxsiHandle Parent)
{
	GtkWidget*	Frame	=	gtk_fixed_new();

	gtk_container_add(GTK_CONTAINER((GtkWidget*)Parent), Frame);

	WindowSystem()->ShowWindow((MaxsiHandle)Frame);

	return (MaxsiHandle)Frame;
}

MaxsiHandle MaxsiControlSystemGTK::CreateLabel(MaxsiHandle Parent)
{
	MaxsiHandle		Control		=	(MaxsiHandle)gtk_label_new(NULL);

	gtk_label_set_line_wrap(GTK_LABEL((GtkLabel*)Control), TRUE);
	gtk_misc_set_alignment(GTK_MISC((GtkWidget*)Control),0.0,0.0);

	WindowSystem()->ShowWindow(Control);

	return Control;
}

MaxsiHandle MaxsiControlSystemGTK::CreateButton(MaxsiHandle Parent)
{
	MaxsiHandle		Control		=	(MaxsiHandle)gtk_button_new();

	WindowSystem()->ShowWindow(Control);

	return Control;
}

MaxsiHandle MaxsiControlSystemGTK::CreateTextSingleLine(MaxsiHandle Parent)
{
	MaxsiHandle		Control		=	(MaxsiHandle)gtk_entry_new();

	WindowSystem()->ShowWindow(Control);

	return Control;
}

MaxsiHandle MaxsiControlSystemGTK::CreateTextMultiLine(MaxsiHandle Parent)
{
	MaxsiHandle		Control		=	(MaxsiHandle)gtk_text_view_new();

	WindowSystem()->ShowWindow(Control);

	return Control;
}

MaxsiHandle MaxsiControlSystemGTK::CreateRadioButton(MaxsiHandle Parent)
{
	MaxsiHandle		Control		=	(MaxsiHandle)gtk_radio_button_new(NULL);

	WindowSystem()->ShowWindow(Control);

	return Control;
}

MaxsiHandle MaxsiControlSystemGTK::CreateCheckButton(MaxsiHandle Parent)
{
	MaxsiHandle		Control		=	(MaxsiHandle)gtk_check_button_new();

	WindowSystem()->ShowWindow(Control);

	return Control;
}

MaxsiHandle MaxsiControlSystemGTK::CreateProgressBar(MaxsiHandle Parent)
{
	MaxsiHandle		Control		=	(MaxsiHandle)gtk_progress_bar_new();

	WindowSystem()->ShowWindow(Control);

	return Control;
}

MaxsiHandle MaxsiControlSystemGTK::CreateTreeView(MaxsiHandle Parent)
{
	MaxsiHandle		Control		=	(MaxsiHandle)gtk_tree_view_new();

	WindowSystem()->ShowWindow(Control);

	return Control;
}

MaxsiHandle MaxsiControlSystemGTK::CreateListView(MaxsiHandle Parent)
{
	MaxsiHandle		Control		=	(MaxsiHandle)gtk_icon_view_new();

	WindowSystem()->ShowWindow(Control);

	return Control;
}

MaxsiHandle MaxsiControlSystemGTK::CreateSeparatorH(MaxsiHandle Parent)
{
	MaxsiHandle		Control		=	(MaxsiHandle)gtk_hseparator_new();

	WindowSystem()->ShowWindow(Control);

	return Control;
}

bool MaxsiControlSystemGTK::SetLabelText(MaxsiHandle Control, MESTR* Text)
{
	if ( Control == NULL ) { return false; }

	char*	TextSL	=	MESTR2CHAR(Text);

	if ( TextSL == NULL ) { return false; }

	gtk_label_set_markup(GTK_LABEL((GtkWidget*)Control), TextSL);

	delete[] TextSL;

	return true;	
}

bool MaxsiControlSystemGTK::SetLabelFont(MaxsiHandle Control, MaxsiHandle Font)
{
#if 0
	MESTR*	Bold	=	BuildString(3, _MESTR("<b>"), Text, _MESTR("</b>"));

	if ( Bold == NULL ) { return false; }

	bool Result = SetLabelText(Control, Bold);

	delete[] Bold;

	return Result;
#endif
	return false;
}

bool MaxsiControlSystemGTK::SetButtonText(MaxsiHandle Control, MESTR* Text)
{
	if ( Control == NULL ) { return false; }

	char*	TextSL	=	MESTR2CHAR(Text);

	if ( TextSL == NULL ) { return false; }

	gtk_button_set_label(GTK_BUTTON((GtkWidget*)Control), TextSL);

	delete[] TextSL;

	return true;	
}

bool MaxsiControlSystemGTK::SetProgress(MaxsiHandle Control, float Progress, size_t Type)
{
	if ( Control == NULL ) { return false; }

	if ( Type == MAXSI_PROGRESS_CURRENT )
	{
		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR((GtkWidget*)Control), Progress);
	}
	else if ( Type == MAXSI_PROGRESS_NORMAL )
	{
		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR((GtkWidget*)Control), Progress);
	}
	else if ( Type == MAXSI_PROGRESS_INDETERMINATE )
	{
		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR((GtkWidget*)Control), Progress);
		return false;
	}
	else if ( Type == MAXSI_PROGRESS_ERROR )
	{
		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR((GtkWidget*)Control), Progress);
		return false;
	}
	else if ( Type == MAXSI_PROGRESS_PAUSED )
	{
		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR((GtkWidget*)Control), Progress);
		return false;
	}
	else
	{
		return false;
	}

	return true;
}


EndMaxsiNamespace

#endif


